package com.ease.web.struts2;

import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
import org.apache.struts2.interceptor.FileUploadInterceptor;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.util.LocalizedTextUtil;

public class FlexFileUploadInterceptor extends FileUploadInterceptor {

	/**
	 *
	 */
	private static final long serialVersionUID = 8228348416312807904L;
	public static final String FILENAME = "uploadFile";
	private static final String DEFAULT_MESSAGE = "no.message.found";

	public String intercept(ActionInvocation invocation) throws Exception {
		ActionContext ac = invocation.getInvocationContext();

		HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);

		if (!(request instanceof MultiPartRequestWrapper)) {
			if (LOG.isDebugEnabled()) {
				ActionProxy proxy = invocation.getProxy();
				LOG.debug(getTextMessage("struts.messages.bypass.request", new Object[] { proxy.getNamespace(), proxy.getActionName() }, ac.getLocale()));
			}

			return invocation.invoke();
		}

		ValidationAware validation = null;

		Object action = invocation.getAction();

		if (action instanceof ValidationAware) {
			validation = (ValidationAware) action;
		}

		MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;

		if (multiWrapper.hasErrors()) {
			for (String error : multiWrapper.getErrors()) {
				if (validation != null) {
					validation.addActionError(error);
				}

				LOG.warn(error);
			}
		}

		// bind allowed Files
		Enumeration<String> fileParameterNames = multiWrapper.getFileParameterNames();
		while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
			// get the value of this input tag
			// 当为flex时,无tag,所以inputName=Filedata;
			// 会影响后续文件的获得
			String inputName = (String) fileParameterNames.nextElement();

			// get the content type
			String[] contentType = multiWrapper.getContentTypes(inputName);

			if (notEmpty(contentType)) {
				// get the name of the file from the input tag
				String[] fileName = multiWrapper.getFileNames(inputName);

				if (notEmpty(fileName)) {
					// get a File object for the uploaded File
					File[] files = multiWrapper.getFiles(inputName);
					if (files != null && files.length > 0) {
						List<File> acceptedFiles = new ArrayList<File>(files.length);
						List<String> acceptedContentTypes = new ArrayList<String>(files.length);
						List<String> acceptedFileNames = new ArrayList<String>(files.length);

						for (int index = 0; index < files.length; index++) {
							if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation, ac.getLocale())) {
								acceptedFiles.add(files[index]);
								acceptedContentTypes.add(contentType[index]);
								acceptedFileNames.add(fileName[index]);
							}
						}

						if (!acceptedFiles.isEmpty()) {
							Map<String, Object> params = ac.getParameters();
							String contentTypeName = inputName + "ContentType";
							String fileNameName = inputName + "FileName";

							params.put(FILENAME, acceptedFiles.toArray(new File[acceptedFiles.size()]));
							params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
							params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
						}
					}
				} else {
					LOG.warn(getTextMessage(action, "struts.messages.invalid.file", new Object[] { inputName }, ac.getLocale()));
				}
			} else {
				LOG.warn(getTextMessage(action, "struts.messages.invalid.content.type", new Object[] { inputName }, ac.getLocale()));
			}
		}

		// invoke action
		String result = invocation.invoke();

		// cleanup
		fileParameterNames = multiWrapper.getFileParameterNames();
		while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
			String inputValue = (String) fileParameterNames.nextElement();
			File[] files = multiWrapper.getFiles(inputValue);

			for (File currentFile : files) {
				if (LOG.isInfoEnabled()) {
					LOG.info(getTextMessage(action, "struts.messages.removing.file", new Object[] { inputValue, currentFile }, ac.getLocale()));
				}

				if ((currentFile != null) && currentFile.isFile()) {
					if (currentFile.delete() == false) {
						LOG.warn("Resource Leaking:  Could not remove uploaded file '" + currentFile.getCanonicalPath() + "'.");
					}
				}
			}
		}

		return result;
	}

	private static boolean notEmpty(Object[] objArray) {
		boolean result = false;
		for (int index = 0; index < objArray.length && !result; index++) {
			if (objArray[index] != null) {
				result = true;
			}
		}
		return result;
	}

	private String getTextMessage(String messageKey, Object[] args, Locale locale) {
		return getTextMessage(null, messageKey, args, locale);
	}

	private String getTextMessage(Object action, String messageKey, Object[] args, Locale locale) {
		if (args == null || args.length == 0) {
			if (action != null && useActionMessageBundle) {
				return LocalizedTextUtil.findText(action.getClass(), messageKey, locale);
			}
			return LocalizedTextUtil.findText(this.getClass(), messageKey, locale);
		} else {
			if (action != null && useActionMessageBundle) {
				return LocalizedTextUtil.findText(action.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
			}
			return LocalizedTextUtil.findText(this.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
		}
	}
}
